package birdsong.dummy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import FollowME.ClientToServerMessage;
import birdsong.comm.ServerSideMessage.Type;

/**
 * A Thread class to manage the message received from a client.
 * 
 * @author Fernando Pereira, Marcos Martins
 * @version 2.0
 */
public class ClientHandler extends Thread {

	private Socket socket;
	private String nickname;

	private ObjectInputStream ois;

	private Map<String, ObjectOutputStream> outPutChannels;
	private LinkedBlockingQueue<ClientToServerMessage> receivedMessages;

	/**
	 * Constructor for a new {@link ClientHandler} thread.
	 * 
	 * @param outPutChannels
	 *            - ObjectOutputStream from connected clients.
	 * 
	 * @param socket
	 *            - Socket for each clientHandler.
	 * @param receivedMessages
	 *            - A list of messages received from clients.
	 * 
	 */
	public ClientHandler(Map<String, ObjectOutputStream> outPutChannels,
			Socket socket,
			LinkedBlockingQueue<ClientToServerMessage> receivedMessages) {
		this.outPutChannels = outPutChannels;
		this.socket = socket;
		this.receivedMessages = receivedMessages;
	}

	/**
	 * Starts the thread and receives a message from the client with the
	 * {@link LinkedBlockingQueue} {@code receivedMessages} the message can goes
	 * from the client to the server. this only stops once the clients output
	 * stream is removed from the {@code outputChannels}
	 */
	@Override
	public void run() {
		try {
			ois = new ObjectInputStream(socket.getInputStream());

			ClientToServerMessage messageFromClient = (ClientToServerMessage) ois
					.readObject();
			if (messageFromClient.getType().equals(Type.CLIENT_CONNECTED)) {
				nickname = messageFromClient.getClientNickname();
				outPutChannels.put(nickname,
						new ObjectOutputStream(socket.getOutputStream()));
				receivedMessages.put(messageFromClient);

				while (outPutChannels.containsKey(nickname)) {
					receivedMessages.put((ClientToServerMessage) ois
							.readObject());
				}
			}
		} catch (ClassNotFoundException e) {
			System.err
					.println("ERROR -  Message class - Server didn't received it");
		} catch (IOException e) {
			outPutChannels.remove(nickname);
			System.err
					.println("ERROR - OutputStream down - OutputStream removed");
		} catch (InterruptedException e) {
			System.err.println("ERROR - Put new messagem on list");
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				System.out.println("ERROR - Closing Socket");
			}
		}
	}
}
